﻿/*
* By Kirkov 2011  (@kirkov)
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcShortRoute
{
    public static class Routes
    {
        private const string RouteNameFormat = "ShortRoute_{0}";

        /// <summary>
        /// Maps the short routes declared by <code>ShortRoute</code> attributes on action methods.
        /// </summary>
        /// <param name="routes">Route collection to register routes on.</param>
        public static void Register(RouteCollection routes)
        {
            Assembly ass = Assembly.GetCallingAssembly();

            IEnumerable<Controller> instances = (from t in ass.GetTypes()
                                                 where t.IsSubclassOf(typeof (Controller))
                                                       && !t.IsAbstract
                                                       && t.GetConstructor(Type.EmptyTypes) != null
                                                 select Activator.CreateInstance(t) as Controller).ToList();

            foreach (Controller controller in instances)
            {
                Type controllerType = controller.GetType();
                MethodInfo[] methods = controllerType.GetMethods();

                foreach (MethodInfo methodInfo in methods)
                {
                    object[] attrs = methodInfo.GetCustomAttributes(typeof (ShortRouteAttribute), false);

                    if (attrs.Length == 0)
                        continue;

                    var shortRoute = (ShortRouteAttribute) attrs[0];
                    string url = shortRoute.Url;

                    if (string.IsNullOrEmpty(url))
                    {
                        url = methodInfo.Name.ToLowerInvariant();
                    }

                    var defaults = new
                                       {
                                           controller = controller.GetType().Name.Replace("Controller", ""),
                                           action = methodInfo.Name
                                       };

                    routes.MapRoute(string.Format(RouteNameFormat, url), url, defaults);
                }
            }
        }
    }
}